package com.cs.deviceManager.mqtt.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cs.deviceManager.device.DeviceEventListener;
import com.cs.deviceManager.device.DeviceTypeManager;
import com.cs.deviceManager.mqtt.MqttUtil;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * 设备事件消息处理器
 * 负责MQTT消息的接收与分发，但不直接处理业务逻辑
 * 业务逻辑应由专门的监听器如DeviceActiveEventListener处理
 */
public class DeviceEventMessageHandler implements MqttCallback {

    private static final Logger log = LoggerFactory.getLogger(DeviceEventMessageHandler.class);

    // 存储所有注册的设备事件监听器
    private final List<DeviceEventListener> listeners = new ArrayList<>();
    // 匹配 IS0360 主题：IS0360-up-50240007
    // IS0360 设备主题匹配模式: IS0360-up-{deviceId}
    private static final Pattern ISO360_TOPIC_PATTERN = Pattern.compile("^IS0360-up-(\\w+)$");

    // 用于跟踪设备数据处理状态的映射表
    // key: deviceId, value: 上次处理数据的时间戳
    private final Map<String, Long> deviceProcessMap = new ConcurrentHashMap<>();

    // 用于存储每个设备的数据处理间隔(毫秒)
    // key: deviceId, value: 数据处理间隔
    private final Map<String, Integer> deviceIntervalMap = new ConcurrentHashMap<>();
    
    private static final int DEFAULT_INTERVAL_SECONDS = 30  * 1000;

    public void addListener(DeviceEventListener listener) {
        listeners.add(listener);
    }

    public void addAlListener(List<DeviceEventListener> list) {
        listeners.addAll(list);
    }
    
    /**
     * 设置设备的数据处理间隔
     * @param deviceId 设备ID
     * @param intervalSeconds 数据处理间隔(秒)
     */
    public void setDeviceDataInterval(String deviceId, int intervalSeconds) {
        if (deviceId != null && intervalSeconds > 0) {
            deviceIntervalMap.put(deviceId, intervalSeconds * 1000); // 转换为毫秒
            log.info("设置设备 {} 的数据处理间隔为 {} 秒", deviceId, intervalSeconds);
        }
    }
    
    /**
     * 获取设备的数据处理间隔
     * @param deviceId 设备ID
     * @return 数据处理间隔(毫秒)
     */
    public int getDeviceDataInterval(String deviceId) {
        return deviceIntervalMap.getOrDefault(deviceId, DEFAULT_INTERVAL_SECONDS);
    }

    @Override
    public void connectionLost(Throwable cause) {
        log.error("MQTT 连接断开", cause);
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) {
        try {
            // 假设主题为 device/123/data
            String deviceId = extractDeviceIdFromDeviceTopic(topic, "data");
            String deviceType = DeviceTypeManager.DEVICE_TYPE_IS0360A;

            if (topic.startsWith("device/") && topic.contains("/data")) {

                MqttUtil.reportHeartbeat(deviceId, deviceType);
                // 判断消息类型：二进制数据还是JSON数据
                if (isBinaryData(message)) {
                    // 固件更新数据
                    // 处理固件更新响应
                    deviceId = extractDeviceIdFromDeviceTopic(topic, "data");
                    if (deviceId != null) {
                        // 通知监听器处理二进制数据
                        notifyDeviceBinary(deviceId, message.getPayload());
                    }
                } else {
                    // 检查是否应该处理这条数据
                    // 设备每1秒发送一次数据，持续30秒，我们只处理第一条（30秒内的第一条）
                    long currentTime = System.currentTimeMillis();
                    Long lastProcessTime = deviceProcessMap.get(deviceId);

                    // 获取设备特定的数据处理间隔，如果没有设置则使用默认值
                    int dataInterval = getDeviceDataInterval(deviceId);
                    
                    // 如果是第一次接收数据，或者距离上次处理已经超过设置的间隔，则处理这条数据
                    if (lastProcessTime == null || (currentTime - lastProcessTime) > dataInterval) {
                        deviceProcessMap.put(deviceId, currentTime);
                        String payloadStr = new String(message.getPayload());
                        log.info("处理设备 {} 的数据 {}", deviceId, payloadStr);
                        // 处理遥测数据
                        notifyDeviceTelemetry(deviceId, payloadStr, deviceType);
                    } else {
                        log.debug("设备 {} 在30秒内已处理过数据，忽略当前数据", deviceId);
                    }
                }
            } else {
                log.warn("未知主题，忽略: {},内容 : {}", topic, new String(message.getPayload()));
            }

        } catch (Exception e) {
            log.error("处理 MQTT 消息失败，topic={}", topic, e);
        }
    }

    /**
     * 判断是否为二进制数据
     *
     * @param message MQTT消息
     * @return true表示是二进制数据，false表示是文本数据
     */
    private boolean isBinaryData(MqttMessage message) {
        byte[] payload = message.getPayload();
        if (payload.length == 0) {
            return false;
        }

        // 尝试将数据解析为JSON格式，如果成功则不是二进制数据
        try {
            String payloadStr = new String(payload, StandardCharsets.UTF_8).trim();
            JSON.parseObject(payloadStr);
            return false;
        } catch (Exception e) {
            // 解析失败，可能是二进制数据
            return true;
        }
    }

    /**
     * 处理设备消息，根据消息内容分发到不同处理方法
     *
     * @param deviceId   设备ID
     * @param payloadStr 消息内容
     * @param deviceType 设备类型
     */
    private void handleDeviceMessage(String deviceId, String payloadStr, String deviceType) {
        // 刷新心跳
        MqttUtil.reportHeartbeat(deviceId, deviceType);

        try {
            // 尝试解析JSON数据
            JSONObject json = JSON.parseObject(payloadStr);
            String type = json.getString("type");

            // 根据消息类型分发处理
            if ("status".equals(type)) {
                // 状态类型消息
                String workStatus = json.getString("workstatus");
                if (workStatus != null) {
                    if ("OK".equalsIgnoreCase(workStatus)) {
                        // 设备恢复正常
                        notifyDeviceRecovered(deviceId, payloadStr);
                    } else {
                        // 设备异常
                        notifyDeviceAbnormality(deviceId, payloadStr);
                    }
                }
            } else {
                // 非状态类型消息，作为文本处理
                notifyDeviceText(deviceId, payloadStr);
            }
        } catch (Exception e) {
            // JSON解析失败，作为普通文本处理
            notifyDeviceText(deviceId, payloadStr);
        }
    }

    /**
     * 处理 IS0360 设备数据
     * 主题: IS0360-up-50240007
     * 数据: {"type":"Heart", "properties":{...}}
     */
    private String handleIso360Data(String topic, String payload) {
        var matcher = ISO360_TOPIC_PATTERN.matcher(topic);
        String deviceId;
        if (matcher.matches()) {
            deviceId = matcher.group(1); // 例如 50240007
        } else {
            deviceId = topic.substring("IS0360-up-".length());
        }
        return deviceId;
    }

    // 从 device/123/data 提取 deviceId
    private String extractDeviceIdFromDeviceTopic(String topic, String suffix) {
        // 格式：device/{id}/online
        String prefix = "device/";
        int startIndex = prefix.length();
        int endIndex = topic.length() - ("/" + suffix).length();
        if (endIndex > startIndex) {
            return topic.substring(startIndex, endIndex);
        }
        return null;
    }

    // --- 通知方法 ---

    private void notifyDeviceConnected(String deviceId) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceConnected(deviceId);
                } catch (Exception e) {
                    log.error("监听器 onDeviceConnected 执行异常", e);
                }
            }
        }
    }

    private void notifyDeviceDisconnected(String deviceId) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceDisconnected(deviceId);
                } catch (Exception e) {
                    log.error("监听器 onDeviceDisconnected 执行异常", e);
                }
            }
        }
    }

    private void notifyDeviceTelemetry(String deviceId, String data, String deviceType) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceTelemetry(deviceId, data);
                } catch (Exception e) {
                    log.error("监听器 onDeviceTelemetry 执行异常", e);
                }
            }
        }
    }

    private void notifyDeviceRecovered(String deviceId, String data) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceRecovered(deviceId, data);
                } catch (Exception e) {
                    log.error("监听器 onDeviceRecovered 执行异常", e);
                }
            }
        }
    }

    private void notifyDeviceAbnormality(String deviceId, String data) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceAbnormality(deviceId, data);
                } catch (Exception e) {
                    log.error("监听器 onDeviceAbnormality 执行异常", e);
                }
            }
        }
    }

    private void notifyDeviceText(String deviceId, String text) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceText(deviceId, text);
                } catch (Exception e) {
                    log.error("监听器 onDeviceText 执行异常", e);
                }
            }
        }
    }

    /**
     * 通知监听器处理二进制数据
     *
     * @param deviceId 设备ID
     * @param data     二进制数据
     */
    private void notifyDeviceBinary(String deviceId, byte[] data) {
        synchronized (listeners) {
            for (DeviceEventListener listener : listeners) {
                try {
                    listener.onDeviceBinary(deviceId, data);
                } catch (Exception e) {
                    log.error("监听器 onDeviceBinary 执行异常", e);
                }
            }
        }
    }


    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        // 可选：QoS 1/2 消息发送完成
    }
}